package org.NooLab.glue.components;

import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
 
import java.util.Vector;

 
import org.NooLab.utilities.logging.PrintLog;
import org.NooLab.utilities.net.GUID;
import org.NooLab.utilities.strings.StringsUtil;

import org.NooLab.glue.MessageBoard;
import org.NooLab.glue.components.pkg.TaskPackage;
import org.NooLab.glue.filter.IboardsReplyHandler;
import org.NooLab.glue.filter.SourceBoardRepliesInterpreter;
import org.NooLab.glue.interfaces.ReceptorDigestIntf;
import org.NooLab.glue.msgframe.BasicMessageParams;
import org.NooLab.glue.msgframe.XRegistration;
import org.NooLab.glue.subscription.FilterPackageIntf;
import org.NooLab.glue.transaction.Transaction;



/**
 * 
 * this component creates and sends data packages to the MessageBoard;
 * 
 * if desired, the component waits until the data are returned, thereby
 * collecting the requested state values of the receptor (via the MessageBoard)
 * 
 * TODO: parameters for the task , transform an object into XML
 *        
 *
 */     
public class DataConnector extends DataConnectorAbs {

	// =================================

	// object references ..............
	 
	TaskPackage taskPackage;
	
	FilterPackageIntf filter ;
	
	SenderConfirmationIntf informSender; 
	
	// points back to MessageReceptorDigester in MessageBoardParticipant
	ReceptorDigestIntf resultsReceiver ;  
	
	// main variables / properties ....

	Map<String,Object> mappedPackagesCollection = new HashMap<String,Object>();
	
	/** a filename, URL, etc. any kind of "address"   */
	String resourceLocator = "";
	
	String nameOfInstance = "";
	
	boolean filterIsActivated;
	
	/** 
	 *  "rawdata,*"  where "*" means "any"
	 *  note that only matching of content types will allow for a transmission of data   
	 */
	String contentType = "" ;
	
	boolean transmitResourceAsReference=false ;
	
	boolean waitingForResults = true;
	
	
	
	
	// constants ......................
	
	

	// volatile variables .............
	
	XRegistration xRegistration ;
	
	long regID = 0;
	
	String sentXML = "";
	
	int protocolID;
	 
	// helper objects .................
	 
	ConnectionSupervisor connex;
	 
	StringsUtil strgutil = new StringsUtil() ;
	
	PrintLog out = new PrintLog(2,true);
	
	
	// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
	public DataConnector( MessageBoardFactory mbfactory, XRegistration xreg, ReceptorDigestIntf resultsreceiver ){
		super(mbfactory, xreg);
		
		xRegistration = xreg ;
		regID = xRegistration.getInstanceID() ;
		
		resultsReceiver = resultsreceiver ;
		
		mbf = mbfactory;
		
		// is null for participants ?
		msgboard = mbf.mb ;  
		 
		connex = new ConnectionSupervisor( msgboard ) ; 
		
		protocolID = mbf.getComBoxFactory().getProtocolID();
	}	
	// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
	
	public void close(){
		connex.isRunning = false;
		connex.enforcedStop();
	}
	
	
	// all message except registration arrive here... which is handled in the registration object itself: method registering()...
	public void update( Observable observedObj, Object objdata ) {
		int r;
		String repliedStr = "";
		
		repliedStr = (String)(objdata);
		
		if (repliedStr==null){
			return;
		}
		
// console print for DEBUG only		
if ((repliedStr!=null) && (repliedStr.contains("cancel x"))){ 
		// &&(repliedStr.contains("<request content") && (repliedStr.contains("return")))){
	out.print(2, "============\nDC: update...");
	out.print(4, ""+repliedStr+"\n============");
}
if ( (repliedStr.contains("reason=\"id"))  ){
	// out.printErr( 2,"(c)  "+repliedStr);
}
		
		if (( repliedStr.toLowerCase().contains("role=\"receptor")) &&
			( protocolID <= MessageBoardFactoryProperties.protocolFTP)){
		 	return;
		}
		
												out.print(5, "\nmessage retrieved by DataConnector...  ");
		if ( repliedStr.contains("<transaction>")){
			
												out.print(5, "msg to DataConnector ... contains:  <transaction> ");
			r = handlingTransmissionReplies( repliedStr ) ;
			                                    if (r<0){
			                                    	out.print(2, "handlingTransmissionReplies() did not complete successfully (r="+r+")! ");
			                                    }
			return;
		}
		
		if ( (repliedStr.contains("<connect>")) || (repliedStr.contains("<relay>")) || (repliedStr.contains("role=\"IBOARD\""))  ){
			r = handlingIBoardCommunication( repliedStr ) ;
			
			if (r==0){
				return;
			}
		}
		
		if ( (repliedStr.contains("<system"))  ){
												out.print(4, " ... contains:  <system...");
			r = handlingSystemMessages( repliedStr ) ;
			
			if (r==0){
				return;
			}
			
		}
		
		if (repliedStr.trim().length()>0){
			out.print(2, "\n\n=============\nunhandled message in DataConnector:\n"+repliedStr+"\n=============\n");
		}else{
			out.print(5, "DataConnector received empty reply string...  ");
		}
	    // all data coming in into the participant are handled here
	}
	
	

	/**
	 * 
	 * 
	 * @param rawXmlStr
	 * @return
	 */
	private int handlingTransmissionReplies( String rawXmlStr ){
		int result = -1;
		
														out.print(3, "handlingTransmissionReplies(0) ... ");
		 
		 
		SourceBoardRepliesInterpreter srcBoardRepliesInterpreter;
		 
		int   r ;
		
if ( ( rawXmlStr.contains("<confirmation secret=")) &&
	 ( rawXmlStr.contains("type=\"taskdata\"")) ){
 r=0;	
}
/* what's about the confirmation in case of RESTlet ? We should not send it again,
   instead, we should put it to a list of open & delivered transactions
   is there a difference to direct transports? 
   
   -> in case of restlet transports, we have to set up a thread that sends polls to the MessageBoard about
      the state of the transactions
*/
		try{
		 
			mbf.getOpenDataDeliveries().setPointofReentry( this );
			srcBoardRepliesInterpreter = new SourceBoardRepliesInterpreter( mbf,  xRegistration, 
					  													    resultsReceiver,  
					  													    informSender,
					  													    taskPackage,filter,
					  													    nameOfInstance, out ) ;
			
			srcBoardRepliesInterpreter.setResourceLocator( resourceLocator) ;
			srcBoardRepliesInterpreter.setContentType( contentType);
			srcBoardRepliesInterpreter.setMappedPackagesCollection(mappedPackagesCollection);
			
			// ensure that this transaction receipt is indeed for us! 
			// The instance has provided its private port, but we check !
			r = srcBoardRepliesInterpreter.rawAcceptanceCheck(rawXmlStr);
			
			if (r==0){
				result = srcBoardRepliesInterpreter.interpretingSingleReplyMessage( rawXmlStr ) ;
			
				if (result<0){
					
					if (rawXmlStr.contains("<resource value=") ){
					//msgboard = mbf.mb ; resultsReceiver
						out.print(3, "message internally relayed!");
						
						if (srcBoardRepliesInterpreter.relayInSessionResponseToDigester( resultsReceiver, rawXmlStr)){
							return 0;
						}
						
					}
					if (rawXmlStr.toLowerCase().contains("role=\"iboard\"")){
						out.printErr(3, "DataConnector drained an iboard message!  ");
						return 0;
					}
					// unhandled message ... show it
					out.printErr(3, "unhandled message, relayInSessionResponseToDigester() has been ignorant!");
					out.print(3, "\n\r\n"+rawXmlStr+"\n-----------------"  ) ;
				}
			} else{
				out.print(2, "raw acceptance test failed (r="+r+"), no appropriate signature found in received message!");
				out.print(2, ""+rawXmlStr+"\n-----------------"  ) ;
			}
			 
			
			result = 0;
			
		}catch(Exception e){
			if (result >=0){
				result = -3;
			}
			out.printErr(2, "Exception in handlingTransmissionReplies(): "+e.getMessage() );
			e.printStackTrace() ;
		}
		
		return result;
		
	}

	private int handlingIBoardCommunication( String rawXmlStr ) {
		int result=-1 ;
		IboardsReplyHandler iboardsReplyHandler;
		
		try{
			
			result = 0;
			//mbf.getParticipantReference().getMrd()   mb.update(null, rawXmlStr) ;
			// move that to the mrd, we have to take a small extra way
			// iboardsReplyHandler = new IboardsReplyHandler(msgboard, out);
			// iboardsReplyHandler.interpretingMessage(rawXmlStr) ;
			// iboardsReplyHandler(rawXmlStr ) ;
			resultsReceiver.performTaskRelay(rawXmlStr);
			 
			
		}catch(Exception e){
			if (result >=0){
				result = -3;
			}
			out.printErr(2, "Exception in handlingIBoardCommunication(): "+e.getMessage() );
			e.printStackTrace() ;
		}
		
	
		return result ;
	}

	private int handlingSystemMessages( String rawXmlStr ) {
		int result=-1 ;
		
		ParticipantsSysMsgInterpreter participantsSysMsgInterpreter;
		
		try{
		
			
			
			participantsSysMsgInterpreter = new ParticipantsSysMsgInterpreter( mbf,  xRegistration, 
					    													   resultsReceiver,  
					    													   nameOfInstance, out ) ;
 
			result = participantsSysMsgInterpreter.interpretingSysMessage( rawXmlStr ) ;
			 
			
		}catch(Exception e){
			if (result >=0){
				result = -3;
			}
			out.printErr(2, "Exception in handlingSystemMessages(): "+e.getMessage() );
			e.printStackTrace() ;
		}
		
		return result;
	}
	
	
	
	// thats purely outgoing
	private int handlingControlTransmissions( long transactionID, String taskname){ //e.g. "cancel" 
		
		int result=-1;
		String xml,privateTransactionIdentifier="", xmlRestPrefix;
		int listenport ;
		
		ConfirmedSender csender ;
		
		try{
			
			                                                   
			// the receiver is for collecting the replies of the MessageBoard
			// while the replies will arrive in the update() method of this class
			listenport = xRegistration.getClientListeningPort() ;
			
												out.print(4,"\n\nsending control message for transaction of instance regID-"+regID+" ,  using port "+listenport) ;
	
			if ((receiver==null) || (receiver.getListenPort()!= listenport)){
				
				{
					// this is a backward directed intf facade to the factory method "createReceiver" !
					
					receiver = comBox.createReceiver(listenport, mbf.getServicePort(), this,  "regID-"+regID );
					mbf.comBoxFactory.setReceiver(receiver) ;
				}
				
			}else{
				if (receiver!=null){
				}
			}
			// still ??
			if (receiver==null){
				out.print(1,"CRITICAL !!! no receiver available for instance "+ xRegistration.getInstanceID()+" (role="+xRegistration.getRole()+")");
				return -7;
			}
				
			privateTransactionIdentifier = GUID.randomvalue() ;
			// 
			String paramStr="" ;
			
												out.print(3, "handlingControlTransmissions(), task : "+taskname);
			
			if (transactionID>0){
				xml = xMessage.createControlTaskMessage( transactionID, taskname, paramStr,
													 	 privateTransactionIdentifier,
													 	 xRegistration.getInstanceID() , xRegistration.getRole()  ) ;
			}else{
				// this needs a better control: some identifier as parameter of the method
				xml = xMessage.createCancelAllTaskMessage(  xRegistration.getNameOfApplicant(), 
															xRegistration.getInstanceID() ,
															privateTransactionIdentifier,
														    "SOURCE", "all");
				/*
				 * the confirmation for the response will be provided by
				 * SourceBoardRepliesInterpreter::handling_ConfirmationAboutTaskRequest(), which calls through
				 * the interfaced method "informSender.informAboutConfirmation(true)"
				 * 
				 */
			}
			
			// the registration should know, whether there is currently a sending process to the MessageBoard by this instance,
			// if yes, the sender should wait a bit
			
			
			// now we need to listen in update for the returned receiptID
			// thus we need a call back to here, which means that we need a small inline sending class -> ConfirmedSender
	
			// this will start a thread for sending, but then also wait inside that thread until a 
			// proper confirmation has been returned return
	
			if (comBox.getFactory().getProtocolID() <= MessageBoardFactoryProperties.protocolFTP){
				if (xml.contains("<meta>")==false){
					xmlRestPrefix = xMessage.createRestletRoutingPrefix("", "data", "post");
					xml =  xmlRestPrefix + xml; // a prolog which will be removed by restlet framework connector
				}
			}
			
			csender = new ConfirmedSender( (mbf.getComBoxFactory().getComBox()), privateTransactionIdentifier, out) ; 
			informSender = csender.start( xml, xRegistration.getActiveport() ) ;
			// TODO XXX: actually, this confirmation handler should be a Collection of a true handler object!!
			//       	 since it needs to be global, there could be overlaps between senders
			// once informed=confirmed, we remove the item from the list
			
												out.print(5,"back from sending the 'cancel' control task...");
			
		}catch(Exception e){
			
		}
		
		
		return result;
	}




	/**
	 * 
	 *  triggering the transmission of data to the MessageBoard
	 *  
	 *  uuidDC is mapping a particular taskpackage
	 *  
	 */
	public void transmitSourceData( String uuidDC ){
		String xml, xmlRestPrefix="";
		
		int listenport ;
		
		                                                   
		// the receiver is for collecting the replies of the MessageBoard
		// while the replies will arrive in the update() method of this class
		listenport = xRegistration.getClientListeningPort() ;
		
														out.print(2,"\n\nstarting transaction for instance regID-"+regID+" ,  using port "+listenport) ;
														  												
		if (mbf.getFactoryProperties().getProtocolId() >= MessageBoardFactoryProperties.protocolTCP){
			// only for direct-connection-transports we need a receiver, 
			// for http... we will either will poll or work on the within-session response
			if ((receiver == null) || (receiver.getListenPort() != listenport)) {
	
					// this is a backward directed intf facade to the factory
					// method "createReceiver" !
	
					receiver = comBox.createReceiver(listenport, mbf.getServicePort(), this, "regID-" + regID);
					mbf.comBoxFactory.setReceiver(receiver);
				
			} else {
				if (receiver != null) {
					// receiver.setObserver( this );
				}
			}
	
			// still no receiver ??
			if (receiver==null){
				out.print(1,"CRITICAL !!! no receiver available for instance "+ xRegistration.getInstanceID()+" (role="+xRegistration.getRole()+")");
			}
	
		} else{  
			// sender.setObserver(messageBoard) ;
			mbf.comBoxFactory.setObserver(this)  ; 
			xmlRestPrefix = xMessage.createRestletRoutingPrefix("", "/data", "put");
		}
			
		// 1.  createRequestForID(), note that we will see the uuidDC reflected in the response !!
		xml = xmlRestPrefix + xMessage.createRequestForID( 	xRegistration.getInstanceID(), xRegistration.getRole(), uuidDC ) ;
		
		
		// now we listen in update for the returned receiptID
		
		//
		sender = comBox.createSender( xRegistration.getActiveport(), mbf.getServicePort(),"" ) ; 
		sender.send(xml) ;
		
		// now we listen in update for the returned result
		
		if (waitingForResults){
			// TODO: send a flag to the MessageBoardFactory, that the system should not be stopped
			
			connex.isActivated = true ;
		}else{
			connex.isRunning = false;
		}
		
	}

	public void transmitCancelCommand( long transactionID ){
		int r;
		
		r = handlingControlTransmissions( transactionID, "cancel" ) ;
			if (r<0){
			}
	}

	
	/**
	 *    
	 * 
	 * 
	 */
	public void transmitReceptorResponse( long transactID , TaskPackage resultPackage ) {
		
		String xmlstr="", xmlRestPrefix ,_role;
		long instanceID ;
		int targetport,r;
		String encodedTaskPackage, dtypeStr, resourcePath, contentTags ; 
		// DataSenderIntf sender;
		
		/* 
		 * we do not send a request for a transaction receipt,... we already have one available;
		 * 
		 * thus we prepare the xml message and send it directly to the MessageBoard  
		 */
		_role = mbf.getFactoryProperties().getParticipantsRole();
		
		
		dtypeStr = resultPackage.getTypeOfProceedings();
		// == task, travel results 
												out.print(4, "data type of package : "+ dtypeStr);
		contentTags = "data";
		
		if (dtypeStr.contains("result")){
			contentTags = "result";
		}
		instanceID = xRegistration.getInstanceID() ;
		 
												out.print(4, "transmitReceptorResponse() for package, transaction id="+transactID+" ");
		
		xmlstr = xMessage.createReceptorResultReturnMsg( instanceID, transactID, "RECEPTOR", xRegistration.getClientListeningPort() );
		
		// replace "<!--##DATA##-->" with the encoded package
		encodedTaskPackage = stringedObj.encode( resultPackage ) ;
		
	 
		xmlstr = xmlstr.replace("<data>\r\n","<data>");xmlstr = xmlstr.replace("<"+contentTags+">\n","<"+contentTags+">");
		xmlstr = xmlstr.replace("\r\n</data>","</data>"); xmlstr = xmlstr.replace("\n</"+contentTags+">","</"+contentTags+">");
		
		// "<data>         <!--##DATA##-->\r\n      </data>" 

		xmlstr = strgutil.replaceAll(xmlstr, "<"+contentTags+"> ", "<"+contentTags+">");
		xmlstr = strgutil.replaceAll(xmlstr, " </"+contentTags+">", "</"+contentTags+">");

				
		xmlstr = xmlstr.replace("<!--##DATA##-->\r\n","<!--##DATA##-->"); xmlstr = xmlstr.replace("<!--##DATA##-->\n","<!--##DATA##-->"); 
		xmlstr = xmlstr.replace("<!--##DATA##-->", encodedTaskPackage);
		
		targetport = xRegistration.getClientListeningPort() ;
		// targetport is NOT the client directly, but the MessageBoard!
		targetport = xRegistration.getActiveport() ; // port for 

		
		
		if ( mbf.protocolID <= MessageBoardFactoryProperties.protocolFTP){
			 
			if (mbf.getFactoryProperties().getParticipantsRole().toLowerCase().contains("receptor")){
				resourcePath = "/results" ;
			// this is defined in "ResourceBindingForReceptors{}"
			} else{
				resourcePath = "/data" ;
			}
			
			xmlRestPrefix = xMessage.createRestletRoutingPrefix("", resourcePath, "post");
			xmlstr =  xmlRestPrefix + xmlstr; // a prolog which will be evaluated and removed by restlet framework connector
		}
												out.print(4, _role+" sending package to MessageBoard") ;
		// sending back to the MessageBoard
		SenderWrap sender = new SenderWrap( mbf.getComBoxFactory().getComBox() );
		
		if (mbf.factoryProperties.participantsRole.toLowerCase().contains("receptor")){
			if (mbf.receptorObserver!=null){
				// here we set the MessageRecptor{} class as observer for the responses of this sending
				sender.setObserver( mbf.receptorObserver) ;
			}
			out.printErr(3,"observer for sending results by RECEPTOR : "+mbf.receptorObserver.toString());
		} // else it remains the DataConnector
		
												out.printErr(3,"transmitReceptorResponse() -> sending :");
												out.printErr(4,xmlstr);
												
// TODO: the receptor sends the result again and again  ... 		
// does this arrive? where is the confirmation ??
		r = sender.sendingMessage(xmlstr, targetport) ;
			if (r<0){
				out.printErr(3, "sendingMessage() failed in transmitReceptorResponse(), code="+r);
			}
		sender = null;
		
		sentXML = xmlstr;
		// --> we need to set  deliveryPad.digestingConfirmation(transactionID)
		// upon response to the send !!!
		// -> what has been sent ??
		
	}
	
	/**
	 * mode: 1 = confirm; 2=notification; 3=simple state.
	 * 
	 * @param instanceID
	 * @param transactID
	 * @param stateValue
	 * @param modeStyle
	 */
	public void transmitReceptorResponse( long instanceID, long transactID, String role, int stateValue, String secret, int modeStyle){
		
		String xmlstr="";
		String xmlRestPrefix="" ;
		int targetport=0,r;
		
		
		role = xRegistration.getRole() ;
		targetport = xRegistration.getActiveport() ;
		
		BasicMessageParams basics = new BasicMessageParams();
		
		basics.transactionID = transactID;
		basics.instanceID = instanceID;
		basics.instanceName = "routed source";
		basics.privateTransactionIdentifier = secret;
		basics.roleOfSender = role ;
		
		xmlstr = xMessage.createConfirmationAboutDelivery(	basics, // transactID, instanceID, secret, role, 
															stateValue, Transaction.decodeTransactionCode(stateValue),"c");

		sender = comBox.createSender( targetport, mbf.getServicePort(),"" );
		if ( mbf.protocolID <= MessageBoardFactoryProperties.protocolFTP){
			 
			String resourcePath = "/state/"+instanceID;
			
			xmlRestPrefix = xMessage.createRestletRoutingPrefix("", resourcePath, "post");
			xmlstr =  xmlRestPrefix + xmlstr; // a prolog which will be removed by restlet framework connector

		}
		
		if (xmlstr.indexOf("%")<0){
			out.print(3,"Confirmation inclusive state value.");
			out.print(4,"xml is ...       "+xmlstr);
		}
		SenderWrap sender = new SenderWrap( mbf.getComBoxFactory().getComBox() );
		r = sender.sendingMessage(xmlstr, xRegistration.getActiveport()) ;
			if (r<0){
				out.printErr(3, "sendingMessage() failed in transmitReceptorResponse(), code="+r);
			}
		sender = null;
	}
	
	
	
	public void transmitReceptorResponse(  long instanceID, long transactID, int stateValue, String description ){
		String xmlstr="";
		int targetport; 
		String role, xmlRestPrefix; 
		 
		/* 
		 * we do not send a request for a transaction receipt,... we already have one available;
		 * 
		 * thus we prepare the xml message and send it directly (back) to the MessageBoard  
		 */

		instanceID = xRegistration.getInstanceID() ;
		role = xRegistration.getRole() ;
		
		// the instance ID may be persistent through hibernation
		// we provide that info to the MessageBaord, (... and indirectly also to the SOURCE)
		xmlstr = xMessage.createReceptorStateMsg( instanceID, role, transactID, stateValue, description);
		
		// of course not to the target port of the receptor...
		// targetport = xRegistration.getClientListeningPort() ;
		// ...but to the board !
		targetport = xRegistration.getActiveport() ;
												out.print(4, "------------ RECEPTOR sending to port "+targetport+": transmitReceptorResponse ");
												out.print(5, "response xml is...  \n"+xmlstr) ;
												
		// direct & naive approach without abstraction  
		// 		sender = new UdpDataSender( xRegistration.getClientListeningPort(), mbf.getServicePort() ) ;
		// via abstraction and factories to make it independent from transport protocol...
		sender = comBox.createSender( targetport, mbf.getServicePort(),"" );
		
		if ( mbf.protocolID <= MessageBoardFactoryProperties.protocolFTP){

			//    /state/{clientid}" ? 
			String resourcePath = "/state/"+instanceID;
			// this is defined in "ResourceBindingForReceptors{}"
			
			xmlRestPrefix = xMessage.createRestletRoutingPrefix("", resourcePath, "post");
			xmlstr =  xmlRestPrefix + xmlstr; // a prolog which will be removed by restlet framework connector

		}
		// if (waitforConfirmation<=0)
		{
			String str="";
			str = "<waitforresponse value=\"0\" />\r\n   ";
			xmlstr = xmlstr.replace("</message", str+"</message");
		}
								 
		sender.send(xmlstr) ;
		
		sender = null;
		// sender.release() ;
		
		/*
		 *  <transaction>
      			<transactionID value="524"/>
      			<instance id="2578"/>
      			<return type="state"/>
      			<state>
         			<item description="" value="20"/>
      			</state>
   			</transaction>
		 */
	}



	/**
	 * 
	 * @param rawXmlMsg the xml to be sent, uses the route /data , http-method "Post" 
	 */
	public void transmitRequestToBoard( String rawXmlMsg ){
		String xmlRestPrefix, role,xml;
	
		
		if ((mbf.getFactoryProperties().getProtocolId() <= MessageBoardFactoryProperties.protocolFTP) ||
		    (mbf.factoryProperties.upLinkPollingAllowedForAllProtocols)){
			
			role = mbf.getParticipantReference().getParticipantsRole().toLowerCase();
			
			if (mbf.getParticipantReference().getBusyState()){
				out.print(2, "DataConnector, transmitRequestToBoard, not sending, since we are busy ...") ;
				return;
			}
			if (mbf.getParticipantReference()!=null){
				if (role.contains("receptor")==false){
					if (mbf.getFactoryProperties().getProtocolId() <= MessageBoardFactoryProperties.protocolFTP){
						
					}
					mbf.comBoxFactory.setObserver(this)  ;
				}
			}else{
				mbf.comBoxFactory.setObserver(this)  ;
			}
			
			if (mbf.getFactoryProperties().getProtocolId() <= MessageBoardFactoryProperties.protocolFTP){
				xmlRestPrefix = xMessage.createRestletRoutingPrefix("", "/data", "post");
			
												out.print(5, "DataConnector, role: '"+role+"' in transmitRequestToBoard, sending ...") ;
												out.print(6, "req msg is :       \r\n"+rawXmlMsg) ;
			    xml = xmlRestPrefix + rawXmlMsg  ;
			}else{
				xml = rawXmlMsg  ;
			}
			
			sender = comBox.createSender( xRegistration.getActiveport() ,mbf.getServicePort(),"" ) ; 
			sender.send(xml) ;
			// http sender is waiting 18000 seconds... if there is no confirmation... 
			if (sender!=null){ sender.release() ; }
			
			sender = null ;
			 
		}
		
	}

	/**
	 * 
	 * this requires that the calling method is preparing the complete message, incl. reference to originator
	 *   
	 * @param xmlstr
	 */
	public void directSend( String xmlstr ){
		
		directSend(xmlstr, this);
	}
	
	public void directSend( String xmlstr, Observer obs ){
		String _role ;
		int port;
		
		if (obs==null){
			obs = this;
		}
		mbf.comBoxFactory.setObserver(obs);
		
		// iBoardPort = mbf.mb.getMsgPortforInterBoard() ;
		port = mbf.getFactoryProperties().getMsgPortforInterBoard() ;
		 
		_role = mbf.getFactoryProperties().getParticipantsRole().toLowerCase();
		
		if (_role.contains("receptor")){
			port = mbf.getFactoryProperties().getMsgPortforReceptors() ;
		};
		if (_role.contains("source")){
			port = mbf.getFactoryProperties().getMsgPortforSources() ;
		};
		if (_role.contains("iboard")){
			port = mbf.getFactoryProperties().getMsgPortforInterBoard() ; // 7007
		};
		 
												out.print( 4,"direct send in DataConnector , msg ... \n"+xmlstr);
		
		 
		sender = comBox.createSender( port, mbf.getServicePort(), "");
		sender.send(xmlstr);

		if (waitingForResults) {
			connex.isActivated = true;
		} else {
			connex.isRunning = false;
		}
	
	
	}
	
	public void simpleSend( String completeUncheckedXml, int waitforConfirmation){
		String xmlout, xmlRestPrefix;
		int r;
		xmlout = completeUncheckedXml ;
		
		if (mbf.getFactoryProperties().getProtocolId() <= MessageBoardFactoryProperties.protocolFTP){
			
			xmlRestPrefix = xMessage.createRestletRoutingPrefix("", "/data", "post");
			
			xmlout = xmlRestPrefix + xmlout  ;
			
			if (waitforConfirmation<=0){
				String str="";
				str = "<waitforresponse value=\"0\" />\r\n   ";
				xmlout = xmlout.replace("</message", str+"</message");
			}
		}
		
		SenderWrap sender = new SenderWrap( mbf.getComBoxFactory().getComBox() );
		r = sender.sendingMessage(xmlout, xRegistration.getActiveport()) ;
			if (r<0){
				out.printErr(3, "sendingMessage() failed in simpleSend(), code="+r);
			}
		sender=null;
	}
	
	public void sendEchoResponse( XRegistration xreg, String name, String xmlstr){
		String xmlout="" , str, checkID="", xmlRestPrefix;
		long iid;
		int r;
		
		
		str = xMessage.readRegistrationsConnectionCheck(xmlstr);
		// str = iid+"::"+checkGUID;
		iid = xreg.getInstanceID();
		checkID = str.replace(""+iid+"::", "") ;
		
		// important: NameOfApplicant is issued by MessageBoard and thus it is only known by
		// this instance here and the MessageBoard, such, it can not be faked
		xmlout = xMessage.createConnectionConfirmMsg( iid, checkID, xreg.getRole(), xreg.getNameOfApplicant() );
		
		
		if (mbf.getFactoryProperties().getProtocolId() <= MessageBoardFactoryProperties.protocolFTP){
			
			xmlRestPrefix = xMessage.createRestletRoutingPrefix("", "/data", "post");
			xmlout = xmlRestPrefix + xmlout  ;
		}

		SenderWrap sender = new SenderWrap( mbf.getComBoxFactory().getComBox() );
		r = sender.sendingMessage(xmlout, xRegistration.getActiveport()) ;
			if (r<0){
				out.printErr(3, "sendingMessage() failed in sendEchoResponse(), code="+r);
			}
		// sender = comBox.createSender( xRegistration.getActiveport(), mbf.getServicePort(),"" );
		// sender.send(xmlout) ;
		sender = null;
	}
	
	// this
	public void resend(String completeXmlMsg) {
	
		// SourceBoardRepliesInterpreter srcBoardRepliesInterpreter;
		
		 
		new SourceBoardRepliesInterpreter( mbf,  xRegistration, 
											resultsReceiver, 
				    						informSender,
				    						taskPackage,filter,
				    						nameOfInstance, out ) ;
  
	}

	public void startWiredServer( int listenport){
		
		if ((receiver == null) || (receiver.getListenPort() != listenport)) {
			
			// this is a backward directed intf facade to the factory
			// method "createReceiver" !
			if (receiver==null){  
				receiver = comBox.createReceiver(listenport, mbf.getServicePort(), this, "regID-" + regID);
			}
			mbf.comBoxFactory.setReceiver(receiver);
		
		}
	}
	
	public void unregisterInstanceFromMessageBoard( XRegistration xeg ){
		String xmlstr="",xmlRestPrefix="";
		int port,r ;
		
		
		xmlstr = xMessage.createUnRegistration( xRegistration.getInstanceID() ,
												xRegistration.getNameOfApplicant(),
												xRegistration.getRole() );
			              // xRegistration.getClientListeningPort(),
		
		if (mbf.getFactoryProperties().getProtocolId() < MessageBoardFactoryProperties.protocolTCP){
			xmlRestPrefix = xMessage.createRestletRoutingPrefix("", "/register", "post");
			xmlstr = xmlRestPrefix + xmlstr;
			port = 0;
		}else{
			port = xRegistration.getActiveport();
		}
												out.print(3, "instance (id:"+xRegistration.getInstanceID()+") is sending unregister message to board ...");
												
		SenderWrap sender = new SenderWrap( mbf.getComBoxFactory().getComBox() );
		r = sender.sendingMessage( xmlstr, port) ;
			if (r<0){
				out.printErr(2, "sendingMessage() failed in unregisterInstanceFromMessageBoard(), code="+r);
			}
		sender=null;
		// sender = comBox.createSender( , mbf.getServicePort(),"" );
		// sender.send(xmlstr) ;
		 
		// here for participants (esp source) this is allowed, 
		// NOT however, for the MessageBoard !!!
		// comBox.removeReceiver( comBox.getReceiver() ) ;
	}

	public void setTransmitResourceAsReference( boolean asRef){
		// if false, the content of the file will be encoded to BASE64
		
		transmitResourceAsReference = asRef;
		
	}
	
	public String taskForRelay(TaskPackage taskpackage){
		String uuid;
		
		uuid = GUID.randomvalue() ;
		
		// we have to create a new one... but keeping the references to the original objects
		taskPackage = taskpackage.clone() ;
		
		mappedPackagesCollection.put(uuid, taskPackage);
		
		return uuid;
	}
	
	public void setData( String strData ){
		// finally, there will be different variants
		
	}
	
	// object is "DataContainer{}"
	public void setData( Object obj , String identifier){
		
	}
	
	
	public Map<String, Object> getMappedPackagesCollection() {
		return mappedPackagesCollection;
	}

	public String getNameOfInstance() {
		return nameOfInstance;
	}




	public void setNameOfInstance(String nameOfInstance) {
		this.nameOfInstance = nameOfInstance;
	}


	public void setDataReceiver( DataReceiverIntf recv){
		receiver = recv;
	}


	

	// ------------------------------------------------------------------------

	public void waitForResults( boolean waitfor ){
		waitingForResults = waitfor;
	}
	
	
	public void setResourceLocator( String resourceloc){
		resourceLocator = resourceloc ;
		
	}

	public void setContentType(String contenttype) {
		this.contentType = contenttype;
	}
	
	public String getContentType() {
		return contentType;
	}


	public String getSentXML() {
		return sentXML;
	}




	public void setFilterReference( FilterPackageIntf filter , boolean filterIsActive ){
		this.filter = filter ;
		this.filterIsActivated = filterIsActive ; 
	}


	public boolean getFilterActivation() {
		return filterIsActivated;
	}

 
	public void setFilterActivation(boolean activationFlag) {
		filterIsActivated = activationFlag;
	}


	class ConnectionSupervisor implements Runnable{
		
		MessageBoard msgboard;
		
		boolean isRunning = false;
		boolean isActivated = false;
		
		Vector<Object> ibMessages;
		private Thread thrd;
		 
		
		public ConnectionSupervisor( MessageBoard mb ){
		
			msgboard = mb ;
			 
			
			thrd = new Thread(this,"DC-ConnectionSupervisor");
			thrd.setName("connex");
			
			thrd.start() ;
		}

		
		public void beginWaiting(){
			isActivated = true;
		}

		 
		@SuppressWarnings("static-access")
		public void run() {
			isRunning = true;
		
			try{

				while ((isRunning) ) {
					
					if (isActivated == false) {

						while ( waitingForResults )   {
							try {
								 // "+" 
								Thread.currentThread().sleep(10);
							} catch (Exception e) {
								// educated silence...
							}

						}
						  
					}else {
						thrd.sleep(10);
					}
					
				} // while ...
				
			}catch(Exception e){
				
			}finally{
				isRunning = false;
				isActivated = false;
			}
		}
		
		@SuppressWarnings("static-access")
		private void delay(int millis){
			try {
					Thread.currentThread().sleep(millis);
			} catch (Exception e) {}
		}
		
		public void enforcedStop(){
			
			if (thrd != null){
				try {
					thrd.interrupt();
				} catch (Exception e) {
				}
				isRunning = false;
				isActivated = false;
				
				delay(50);
			}
		}

		public boolean isRunning() {
			return isRunning;
		}
	} // InBufferHandler
}
